<?php
/**
 * Created by PhpStorm.
 * User: itholiday@126.com
 * Date: 2019-03-20
 * Time: 15:43
 * Description:  公共函数
 * Power: haive整理封装
 */
load()->func('file');
define('DS', '/');
define('APP_MODE', 'common');//coomon,sae等
define('USER_NOT_LOGIN', 10001);//用户未登录
define('USER_NOT_FULL', 10002);//用户未完善信息

function cutstr_html($string)
{
    $string = strip_tags($string);
    $string = trim($string);
    $string = preg_replace("/\t/", "", $string);
    $string = preg_replace("/\r\n/", "", $string);
    $string = preg_replace("/\r/", "", $string);
    $string = preg_replace("/\n/", "", $string);
    $string = preg_replace("/ /", "", $string);
    return trim($string);
}

function cmf_get_qrcode($url = '', $size = 150, $bg = '../addons/yq_haircircle/static/images/qrcode-background.jpg')
{
    try {
        $file = IA_ROOT . '/addons/' . ModuleName() . '/api/QRcode.php';
        if (is_file($file)) {
            require_once $file;
        } else {
            return false;
        }

        $file = IA_ROOT . '/addons/' . ModuleName() . '/api/think-image/Image.php';
        if (is_file($file)) {
            require_once $file;
        } else {
            return false;
        }

        $url = empty($url) ? 'http://' . $_SERVER['HTTP_HOST'] : $url;

        $savepath = '../attachment/qrcode/' . date('Ymd') . DS . md5(time() . uniqid()) . '.png';
        $filedir = '../attachment/qrcode/' . date('Ymd');

        if (!file_exists($filedir)) {
            mkdirs($filedir);
        }

        $errorCorrectionLevel = 'L';//容错级别
        $matrixPointSize = floor($size / 37 * 100) / 100 + 0.01;;//生成图片大小

        //生成二维码图片
        QRcode::png($url, $savepath, $errorCorrectionLevel, $matrixPointSize, 2, false);

        if (!is_file($savepath)) return false;

        if (!$bg) return cmf_asset_relative_url($savepath);

        // 生成海报
        if (!file_exists($bg)) {
            return false;
        }
        $fileName = 'poster_' . md5(time() . uniqid()) . '.png';// 文件名
        $image = \think\Image::open($bg);// 宣传海报背景图
        $waterImg = $image->water($savepath, [100, 328]);// 添加图片水印
        $saveWaterImg = $image->save($filedir . DS . $fileName);// 保存图片
        if (!$waterImg || !$saveWaterImg) {
            return false;
        }
        // 删除原图片
        @unlink($savepath);
        return cmf_asset_relative_url('qrcode/' . date('Ymd') . DS . $fileName);
    } catch (\Exception $e) {
        pre_dump($e->getMessage());
    }
}

function isCreditNo($vStr)
{
    $vCity = array(
        '11', '12', '13', '14', '15', '21', '22',
        '23', '31', '32', '33', '34', '35', '36',
        '37', '41', '42', '43', '44', '45', '46',
        '50', '51', '52', '53', '54', '61', '62',
        '63', '64', '65', '71', '81', '82', '91'
    );
    if (!preg_match('/^([\d]{17}[xX\d]|[\d]{15})$/', $vStr)) return false;
    if (!in_array(substr($vStr, 0, 2), $vCity)) return false;
    $vStr = preg_replace('/[xX]$/i', 'a', $vStr);
    $vLength = strlen($vStr);
    if ($vLength == 18) {
        $vBirthday = substr($vStr, 6, 4) . '-' . substr($vStr, 10, 2) . '-' . substr($vStr, 12, 2);
    } else {
        $vBirthday = '19' . substr($vStr, 6, 2) . '-' . substr($vStr, 8, 2) . '-' . substr($vStr, 10, 2);
    }
    if (date('Y-m-d', strtotime($vBirthday)) != $vBirthday) return false;
    if ($vLength == 18) {
        $vSum = 0;
        for ($i = 17; $i >= 0; $i--) {
            $vSubStr = substr($vStr, 17 - $i, 1);
            $vSum += (pow(2, $i) % 11) * (($vSubStr == 'a') ? 10 : intval($vSubStr, 11));
        }
        if ($vSum % 11 != 1) return false;
    }
    return true;
}

function checkIdno($no)
{
    if (!$no) {
        return false;
    }
    $arr_no = str_split($no);

    $last_n = $arr_no[count($arr_no) - 1];
    krsort($arr_no);

    $i = 1;
    $total = 0;
    foreach ($arr_no as $n) {
        if ($i % 2 == 0) {
            $ix = $n * 2;
            if ($ix >= 10) {
                $nx = 1 + ($ix % 10);
                $total += $nx;
            } else {
                $total += $ix;
            }
        } else {
            $total += $n;
        }
        $i++;
    }
    $total -= $last_n;
    $total *= 9;
    if ($last_n == ($total % 10)) {
        return true;
    }
}

function checkTruename($name)
{
    if (strlen($name) < 6) {
        return false;
    }
    //新疆等少数民族可能有·
    if (strpos($name, '·')) {
        //将·去掉，看看剩下的是不是都是中文
        $str = str_replace("·", '', $name);
        if (!preg_match('/^[\x7f-\xff]+$/', $name)) {
            //不全是中文
            return false;
        }
    } else {
        if (!preg_match('/^[\x7f-\xff]+$/', $name)) {
            //不全是中文
            return false;
        }
    }
    return true;
}

//if(!function_exists('mkdirs')){
//    function mkdirs($dir, $mode = 0777)
//    {
//        if (is_dir($dir) || mkdir($dir, $mode)) return TRUE;
//        if (!mkdirs(dirname($dir), $mode)) return FALSE;
//        return mkdir($dir, $mode);
//    }
//}
//防止sql注入、转义
function escapeString($content)
{
    $pattern = "/(select[\s])|(insert[\s])|(update[\s])|(delete[\s])|(from[\s])|(where[\s])|(drop[\s])/i";
    if (is_array($content)) {
        foreach ($content as $key => $value) {
            $content[$key] = addslashes(trim($value));
            if (preg_match($pattern, $content[$key])) {
                $content[$key] = '';
            }
        }
    } else {
        $content = addslashes(trim($content));
        if (preg_match($pattern, $content)) {
            $content = '';
        }
    }
    return $content;
}


function checkMobileLogin($redirect = false)
{
    if (session('user_id')) {
        return true;
    } else {
        if ($redirect) {
            redirect(url('entry//public', array('m' => 'yq_haircircle', 'op' => 'login')));//跳到登录页面
        }
        return false;
    }
}

/**
 * session管理函数
 * @param string|array $name session名称 如果为数组则表示进行session设置
 * @param mixed $value session值
 * @return mixed
 */
function session($name = '', $value = '')
{
    $prefix = cmf_config('SESSION_PREFIX');
    if (is_array($name)) {
        // session初始化 在session_start 之前调用
        if (isset($name['prefix'])) {
            cmf_config('SESSION_PREFIX', $name['prefix']);
        }

        if (cmf_config('VAR_SESSION_ID') && isset($_REQUEST[cmf_config('VAR_SESSION_ID')])) {
            session_id($_REQUEST[cmf_config('VAR_SESSION_ID')]);
        } elseif (isset($name['id'])) {
            session_id($name['id']);
        }
        if ('common' == APP_MODE) {
            // 其它模式可能不支持
            ini_set('session.auto_start', 0);
        }
        if (isset($name['name'])) {
            session_name($name['name']);
        }

        if (isset($name['path'])) {
            session_save_path($name['path']);
        }

        if (isset($name['domain'])) {
            ini_set('session.cookie_domain', $name['domain']);
        }

        if (isset($name['expire'])) {
            ini_set('session.gc_maxlifetime', $name['expire']);
            ini_set('session.cookie_lifetime', $name['expire']);
        }
        if (isset($name['use_trans_sid'])) {
            ini_set('session.use_trans_sid', $name['use_trans_sid'] ? 1 : 0);
        }

        if (isset($name['use_cookies'])) {
            ini_set('session.use_cookies', $name['use_cookies'] ? 1 : 0);
        }

        if (isset($name['cache_limiter'])) {
            session_cache_limiter($name['cache_limiter']);
        }

        if (isset($name['cache_expire'])) {
            session_cache_expire($name['cache_expire']);
        }

        if (isset($name['type'])) {
            cmf_config('SESSION_TYPE', $name['type']);
        }

        // 启动session
        if (cmf_config('SESSION_AUTO_START')) {
            session_start();
        }

    } elseif ('' === $value) {
        if ('' === $name) {
            // 获取全部的session
            return $prefix ? $_SESSION[$prefix] : $_SESSION;
        } elseif (0 === strpos($name, '[')) {
            // session 操作
            if ('[pause]' == $name) {
                // 暂停session
                session_write_close();
            } elseif ('[start]' == $name) {
                // 启动session
                session_start();
            } elseif ('[destroy]' == $name) {
                // 销毁session
                $_SESSION = array();
                session_unset();
                session_destroy();
            } elseif ('[regenerate]' == $name) {
                // 重新生成id
                session_regenerate_id();
            }
        } elseif (0 === strpos($name, '?')) {
            // 检查session
            $name = substr($name, 1);
            if (strpos($name, '.')) {
                // 支持数组
                list($name1, $name2) = explode('.', $name);
                return $prefix ? isset($_SESSION[$prefix][$name1][$name2]) : isset($_SESSION[$name1][$name2]);
            } else {
                return $prefix ? isset($_SESSION[$prefix][$name]) : isset($_SESSION[$name]);
            }
        } elseif (is_null($name)) {
            // 清空session
            if ($prefix) {
                unset($_SESSION[$prefix]);
            } else {
                $_SESSION = array();
            }
        } elseif ($prefix) {
            // 获取session
            if (strpos($name, '.')) {
                list($name1, $name2) = explode('.', $name);
                return isset($_SESSION[$prefix][$name1][$name2]) ? $_SESSION[$prefix][$name1][$name2] : null;
            } else {
                return isset($_SESSION[$prefix][$name]) ? $_SESSION[$prefix][$name] : null;
            }
        } else {
            if (strpos($name, '.')) {
                list($name1, $name2) = explode('.', $name);
                return isset($_SESSION[$name1][$name2]) ? $_SESSION[$name1][$name2] : null;
            } else {
                return isset($_SESSION[$name]) ? $_SESSION[$name] : null;
            }
        }
    } elseif (is_null($value)) {
        // 删除session
        if (strpos($name, '.')) {
            list($name1, $name2) = explode('.', $name);
            if ($prefix) {
                unset($_SESSION[$prefix][$name1][$name2]);
            } else {
                unset($_SESSION[$name1][$name2]);
            }
        } else {
            if ($prefix) {
                unset($_SESSION[$prefix][$name]);
            } else {
                unset($_SESSION[$name]);
            }
        }
    } else {
        // 设置session
        if (strpos($name, '.')) {
            list($name1, $name2) = explode('.', $name);
            if ($prefix) {
                $_SESSION[$prefix][$name1][$name2] = $value;
            } else {
                $_SESSION[$name1][$name2] = $value;
            }
        } else {
            if ($prefix) {
                $_SESSION[$prefix][$name] = $value;
            } else {
                $_SESSION[$name] = $value;
            }
        }
    }
    return null;
}

/**
 * Cookie 设置、获取、删除
 * @param string $name cookie名称
 * @param mixed $value cookie值
 * @param mixed $option cookie参数
 * @return mixed
 */
function cookie($name = '', $value = '', $option = null)
{
    // 默认设置
    $config = array(
        'prefix' => cmf_config('COOKIE_PREFIX'), // cookie 名称前缀
        'expire' => cmf_config('COOKIE_EXPIRE'), // cookie 保存时间
        'path' => cmf_config('COOKIE_PATH'), // cookie 保存路径
        'domain' => cmf_config('COOKIE_DOMAIN'), // cookie 有效域名
        'secure' => cmf_config('COOKIE_SECURE'), //  cookie 启用安全传输
        'httponly' => cmf_config('COOKIE_HTTPONLY'), // httponly设置
    );
    // 参数设置(会覆盖黙认设置)
    if (!is_null($option)) {
        if (is_numeric($option)) {
            $option = array('expire' => $option);
        } elseif (is_string($option)) {
            parse_str($option, $option);
        }

        $config = array_merge($config, array_change_key_case($option));
    }
    if (!empty($config['httponly'])) {
        ini_set("session.cookie_httponly", 1);
    }
    // 清除指定前缀的所有cookie
    if (is_null($name)) {
        if (empty($_COOKIE)) {
            return null;
        }

        // 要删除的cookie前缀，不指定则删除config设置的指定前缀
        $prefix = empty($value) ? $config['prefix'] : $value;
        if (!empty($prefix)) {
            // 如果前缀为空字符串将不作处理直接返回
            foreach ($_COOKIE as $key => $val) {
                if (0 === stripos($key, $prefix)) {
                    setcookie($key, '', time() - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
                    unset($_COOKIE[$key]);
                }
            }
        }
        return null;
    } elseif ('' === $name) {
        // 获取全部的cookie
        return $_COOKIE;
    }
    $name = $config['prefix'] . str_replace('.', '_', $name);
    if ('' === $value) {
        if (isset($_COOKIE[$name])) {
            $value = $_COOKIE[$name];
            if (0 === strpos($value, 'think:')) {
                $value = substr($value, 6);
                return array_map('urldecode', json_decode(MAGIC_QUOTES_GPC ? stripslashes($value) : $value, true));
            } else {
                return $value;
            }
        } else {
            return null;
        }
    } else {
        if (is_null($value)) {
            setcookie($name, '', time() - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
            unset($_COOKIE[$name]); // 删除指定cookie
        } else {
            // 设置cookie
            if (is_array($value)) {
                $value = 'think:' . json_encode(array_map('urlencode', $value));
            }
            $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
            setcookie($name, $value, $expire, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
            $_COOKIE[$name] = $value;
        }
    }
    return null;
}

/**
 * @param $data 要整理的数据(全部或者某个分类及下级)
 * @param int $id 0或者分类ID
 * @param int $lev
 * @param bool $iscache
 * @return array
 */
function getTree($data, $id = 0, $lev = 1, $iscache = true)
{
    static $list = array();
    //根据参数决定是否需要重置
    if (!$iscache) {
        $list = array();
    }
    foreach ($data as $key => $value) {
        if ($value['pid'] == $id) {
            $value['lv'] = $lev;
            $list[] = $value;
            //使用递归的方式获取分类下的子分类
            getTree($data, $value['id'], $lev + 1);
        }
    }
    return $list;
}

if (!function_exists('pdo_update_all')) {
    function pdo_update_all($table, $data = array())
    {
        if (count($data) == count($data, 1)) return false;
        $data = array_merge($data);
        $sql = '';
        $insert = 'replace into ';
        $keys_str = '';
        foreach (array_keys($data[0]) as $val) {
            $keys_str .= "`$val`,";
        }
        $keys_str = trim($keys_str, ',');
        $values_str = '';
        foreach ($data as $key => $val) {
            $tmp = '';
            foreach (array_values($val) as $v) {
                $tmp .= "'$v',";
            }
            $tmp = trim($tmp, ',');
            $values_str .= "({$tmp}),";
        }
        $values_str = trim($values_str, ',');
        $sql .= $insert . tablename($table) . ' (' . $keys_str . ') values ' . $values_str;
        return pdo_query($sql);
    }
}
if (!function_exists('pdo_insert_all')) {
    function pdo_insert_all($table, $data = array(), $replace = FALSE)
    {
        if (count($data) == count($data, 1)) return false;
        $data = array_merge($data);
        $sql = '';
        $insert = 'insert into ';
        $replace && $insert = 'replace into ';
        $keys_str = '';
        foreach (array_keys($data[0]) as $val) {
            $keys_str .= "`$val`,";
        }
        $keys_str = trim($keys_str, ',');
        $values_str = '';
        foreach ($data as $key => $val) {
            $tmp = '';
            foreach (array_values($val) as $v) {
                $tmp .= "'$v',";
            }
            $tmp = trim($tmp, ',');
            $values_str .= "({$tmp}),";
        }
        $values_str = trim($values_str, ',');
        $sql .= $insert . tablename($table) . ' (' . $keys_str . ') values ' . $values_str;
        return pdo_query($sql);
    }
}

function pre_dump($param, $exit = true)
{
    echo '<pre>';
    print_r($param);
    $exit && exit;
}

/**
 * 分类路径配置
 * @param  string $pid 数据表,父id
 * @return null
 * @author App <itholiday@126.com>
 */
function setPath($pid)
{
    $list = pdo_get('yq_haircircle_task_cate', array('id' => $pid), ['id', 'path']);
    $path = $list['path'] . '-' . $list['id'];
    $lv = count(explode('-', $path));
    return array('path' => $path, 'lv' => $lv);
}

/**
 * SonCate配置
 * @param  string $m ,$pid 数据表,父id
 * @return null
 * @author App <itholiday@126.com>
 */
function setSoncate($pid)
{
    $father = pdo_get('yq_haircircle_task_cate', array('id' => $pid));
    $son = pdo_getall('yq_haircircle_task_cate', array('pid' => $pid), array('id'));
    if ($son && $father) {
        //存在子栏目
        $arr = '';
        foreach ($son as $k => $v) {
            $arr = $arr . $v['id'] . ',';
        }
        $data['soncate'] = $arr;
        $rf = pdo_update('yq_haircircle_task_cate', $data, array('id' => $father['id']));
        if (empty($rf)) {
            return FALSE;
        } else {
            return TRUE;
        }
    } else {
        $data['soncate'] = '';
        $rf = pdo_update('yq_haircircle_task_cate', $data, array('id' => $father['id']));
        if (empty($rf)) {
            return FALSE;
        } else {
            return TRUE;
        }
    }
}

/**
 * 获取分类
 * @param  string $m
 * @return array
 */
function getCate($m, $where = '')
{
    $cates = array();
    $list = $m->where($where)->select();
    foreach ($list as $k => $v) {
        $cates[$v['id']] = $v['name'];
    }
    return $cates;
}

/**
 * AppTree快速无限分类树
 * @param  string $m ,$pid 数据表,父id
 * @return null
 * @author App <itholiday@126.com>
 */
function appTree($pid, $field, $map, $order = 'sorts desc', $keyid = 'id', $keypid = 'pid', $tree = true, $keychild = '_child')
{
    $sql = "select $field from ims_yq_haircircle_task_cate where $map order by $order";
    $list = pdo_fetchall($sql);
    if ($tree) {
        $list = list_to_tree($list, $keyid, $keypid, $keychild, $root = $pid);//无限
    } else {
        $list = array();
        $list = list_to_treelist($list, $keyid, $keypid, $root = $pid);//二维
    }
    return $list;
}


/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 * @return array
 */
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0)
{
    // 创建Tree
    $tree = array();
    if (is_array($list)) {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] = &$list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[] = &$list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent = &$refer[$parentId];
                    $parent[$child][] = &$list[$key];
                }
            }
        }
    }
    return $tree;
}

/**
 * desription 压缩图片
 * @param sting $imgsrc 图片路径
 * @param string $imgdst 压缩后保存路径
 */

function image_png_size_add($imgsrc, $imgdst)
{
    if (!is_file($imgsrc)) {
        return false;
    }
    if (!is_dir(dirname($imgdst))) {
        mkdirs(dirname($imgdst));
    }
    list($width, $height, $type) = getimagesize($imgsrc);
    $new_width = ($width > 600 ? 600 : $width) * 0.9;
    $new_height = ($height > 600 ? 600 : $height) * 0.9;
    switch ($type) {
        case 1:
            $giftype = check_gifcartoon($imgsrc);
            if ($giftype) {
                header('Content-Type:image/gif');
                $image_wp = imagecreatetruecolor($new_width, $new_height);
                $image = imagecreatefromgif($imgsrc);
                imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
                imagejpeg($image_wp, $imgdst, 75);
                imagedestroy($image_wp);
            }
            break;
        case 2:
            header('Content-Type:image/jpeg');
            $image_wp = imagecreatetruecolor($new_width, $new_height);
            $image = imagecreatefromjpeg($imgsrc);
            imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
            imagejpeg($image_wp, $imgdst, 75);
            imagedestroy($image_wp);
            break;
        case 3:
            header('Content-Type:image/png');
            $image_wp = imagecreatetruecolor($new_width, $new_height);
            $image = imagecreatefrompng($imgsrc);
            imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
            imagejpeg($image_wp, $imgdst, 75);
            imagedestroy($image_wp);
            break;
    }
    if (is_file($imgdst)) {
        @unlink($imgsrc);
        return true;
    }
    return false;
}

/**
 * desription 判断是否gif动画
 * @param sting $image_file图片路径
 * @return boolean t 是 f 否
 */
function check_gifcartoon($image_file)
{
    is_file($image_file) or die;
    $fp = fopen($image_file, 'rb');
    $image_head = fread($fp, 1024);
    fclose($fp);
    return preg_match("/" . chr(0x21) . chr(0xff) . chr(0x0b) . 'NETSCAPE2.0' . "/", $image_head) ? false : true;
}

/**
 * 获取文件相对路径
 * @param string $assetUrl 文件的URL
 * @return string
 */
function cmf_asset_relative_url($assetUrl)
{
    if (empty($assetUrl)) return '';
    if (strpos($assetUrl, "http") === 0) {
        $host_param = parse_url($assetUrl);
        if($host_param['host'] == $_SERVER['SERVER_NAME']){
            return str_replace('/attachment/','',$host_param['path']);
        }else{
            return $assetUrl;
        }
    } else {
        $assetUrl = trim($assetUrl,'.');
        return str_replace('/attachment/', '', $assetUrl);
    }
}

function cmf_get_upload_url($file)
{
    if (empty($file)) {
        return '';
    }

    if (strpos($file, "http") === 0) {
        return $file;
    } else if (strpos($file, "/") === 0) {
        return 'http://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER["SERVER_PORT"] . $file;
    } else {
        return 'http://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER["SERVER_PORT"] . '/attachment/' . $file;
    }
}

/**
 * 导出excel
 * @param array $data 导入数据
 * @param string $savefile 导出excel文件名
 * @param array $fileheader excel的表头
 * @param string $sheetname sheet的标题名
 */
function exportExcel($data, $savefile, $fileheader, $sheetname)
{
    //引入phpexcel核心文件，不是tp，你也可以用include（‘文件路径’）来引入
    $file = IA_ROOT . '/addons/' . ModuleName() . '/api/phpexcel/Classes/PHPExcel.php';
    if (is_file($file)) {
        require_once $file;
    } else {
        return false;
    }
    $excel = new \PHPExcel();
    if (is_null($savefile)) {
        $savefile = time();
    } else {
        //防止中文命名，下载时ie9及其他情况下的文件名称乱码
        iconv('UTF-8', 'GB2312', $savefile);
    }
    //设置excel属性
    $objActSheet = $excel->getActiveSheet();
    //根据有生成的excel多少列，$letter长度要大于等于这个值
    $letter = array(
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM',
        'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ'
    );
    //设置当前的sheet
    $excel->setActiveSheetIndex(0);
    //设置sheet的name
    $objActSheet->setTitle($sheetname);
    //设置表头
    for ($i = 0; $i < count($fileheader); $i++) {
        //单元宽度自适应,1.8.1版本phpexcel中文支持勉强可以，自适应后单独设置宽度无效
        //$objActSheet->getColumnDimension("$letter[$i]")->setAutoSize(true);
        //设置表头值，这里的setCellValue第二个参数不能使用iconv，否则excel中显示false
        $objActSheet->setCellValue("$letter[$i]1", $fileheader[$i]);
        //设置表头字体样式
        $objActSheet->getStyle("$letter[$i]1")->getFont()->setName('微软雅黑');
        //设置表头字体大小
        $objActSheet->getStyle("$letter[$i]1")->getFont()->setSize(12);
        //设置表头字体是否加粗
        $objActSheet->getStyle("$letter[$i]1")->getFont()->setBold(true);
        //设置表头文字垂直居中
        $objActSheet->getStyle("$letter[$i]1")->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        //设置文字上下居中
        $objActSheet->getStyle($letter[$i])->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
        //设置表头外的文字垂直居中
        $excel->setActiveSheetIndex(0)->getStyle($letter[$i])->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
    }
    //单独设置D列宽度为15
    $objActSheet->getColumnDimension('B')->setWidth(25);
    $objActSheet->getColumnDimension('D')->setWidth(25);
    $objActSheet->getColumnDimension('H')->setWidth(30);
    $objActSheet->getColumnDimension('I')->setWidth(30);
    $objActSheet->getColumnDimension('J')->setWidth(30);
    $objActSheet->getColumnDimension('K')->setWidth(30);
    $objActSheet->getColumnDimension('L')->setWidth(30);
    //这里$i初始值设置为2，$j初始值设置为0，自己体会原因
    for ($i = 2; $i <= count($data) + 1; $i++) {
        $j = 0;
        foreach ($data[$i - 2] as $key => $value) {
            //不是图片时将数据加入到excel，这里数据库存的图片字段是img
            if ($key != 'img') {
                $objActSheet->setCellValue("$letter[$j]$i", $value);
            }
            //是图片是加入图片到excel
            if ($key == 'img') {
                if ($value != '') {
                    $value = iconv("UTF-8", "GB2312", $value); //防止中文命名的文件
                    // 图片生成
                    $objDrawing[$key] = new \PHPExcel_Worksheet_Drawing();
                    // 图片地址
                    $objDrawing[$key]->setPath('.\Uploads' . $value);
                    // 设置图片宽度高度
                    $objDrawing[$key]->setHeight('80px'); //照片高度
                    $objDrawing[$key]->setWidth('80px'); //照片宽度
                    // 设置图片要插入的单元格
                    $objDrawing[$key]->setCoordinates('D' . $i);
                    // 图片偏移距离
                    $objDrawing[$key]->setOffsetX(12);
                    $objDrawing[$key]->setOffsetY(12);
                    //下边两行不知道对图片单元格的格式有什么作用，有知道的要告诉我哟^_^
                    //$objDrawing[$key]->getShadow()->setVisible(true);
                    //$objDrawing[$key]->getShadow()->setDirection(50);
                    $objDrawing[$key]->setWorksheet($objActSheet);
                }
            }
            $j++;
        }
        //设置单元格高度，暂时没有找到统一设置高度方法
        $objActSheet->getRowDimension($i)->setRowHeight('80px');
    }
    header('Content-Type: application/vnd.ms-excel');
//        下载的excel文件名称，为Excel5，后缀为xls，不过影响似乎不大
    header('Content-Disposition: attachment;filename="' . $savefile . '.xlsx"');
    header('Cache-Control: max-age=0');
    // 用户下载excel
    ob_clean();
    $objWriter = \PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
    $objWriter->save('php://output');
    // 保存excel在服务器上
    //$objWriter = new PHPExcel_Writer_Excel2007($excel);
    //或者$objWriter = new PHPExcel_Writer_Excel5($excel);
    //$objWriter->save("保存的文件地址/".$savefile);
}

function array_map_recursive($filter, $data)
{
    $result = array();
    foreach ($data as $key => $val) {
        $result[$key] = is_array($val)
            ? array_map_recursive($filter, $val)
            : call_user_func($filter, $val);
    }
    return $result;
}

/**
 * 获取输入参数 支持过滤和默认值
 * 使用方法:
 * <code>
 * input('id',0); 获取id参数 自动判断get或者post
 * input('post.name','','htmlspecialchars'); 获取$_POST['name']
 * input('get.'); 获取$_GET
 * </code>
 * @param string $name 变量的名称 支持指定类型
 * @param mixed $default 不存在的时候默认值
 * @param mixed $filter 参数过滤方法
 * @param mixed $datas 要获取的额外数据源
 * @return mixed
 */
function input($name, $default = '', $filter = null, $datas = null)
{
    static $_PUT = null;
    if (strpos($name, '/')) { // 指定修饰符
        list($name, $type) = explode('/', $name, 2);
    }
    if (strpos($name, '.')) { // 指定参数来源
        list($method, $name) = explode('.', $name, 2);
    } else { // 默认为自动判断
        $method = 'param';
    }
    switch (strtolower($method)) {
        case 'get'     :
            $input =& $_GET;
            break;
        case 'post'    :
            $input =& $_POST;
            break;
        case 'put'     :
            if (is_null($_PUT)) {
                parse_str(file_get_contents('php://input'), $_PUT);
            }
            $input = $_PUT;
            break;
        case 'param'   :
            switch ($_SERVER['REQUEST_METHOD']) {
                case 'POST':
                    $input = $_POST;
                    break;
                case 'PUT':
                    if (is_null($_PUT)) {
                        parse_str(file_get_contents('php://input'), $_PUT);
                    }
                    $input = $_PUT;
                    break;
                default:
                    $input = $_GET;
            }
            break;
        case 'path'    :
            $input = array();
            if (!empty($_SERVER['PATH_INFO'])) {
                $depr = '/';
                $input = explode($depr, trim($_SERVER['PATH_INFO'], $depr));
            }
            break;
        case 'request' :
            $input =& $_REQUEST;
            break;
        case 'session' :
            $input =& $_SESSION;
            break;
        case 'cookie'  :
            $input =& $_COOKIE;
            break;
        case 'server'  :
            $input =& $_SERVER;
            break;
        case 'globals' :
            $input =& $GLOBALS;
            break;
        case 'data'    :
            $input =& $datas;
            break;
        default:
            return null;
    }
    if ('' == $name) { // 获取全部变量
        $data = $input;
        $filters = isset($filter) ? $filter : 'htmlspecialchars';
        if ($filters) {
            if (is_string($filters)) {
                $filters = explode(',', $filters);
            }
            foreach ($filters as $filter) {
                $data = array_map_recursive($filter, $data); // 参数过滤
            }
        }
    } elseif (isset($input[$name])) { // 取值操作
        $data = $input[$name];
        $filters = isset($filter) ? $filter : 'htmlspecialchars';
        if ($filters) {
            if (is_string($filters)) {
                if (0 === strpos($filters, '/')) {
                    if (1 !== preg_match($filters, (string)$data)) {
                        // 支持正则验证
                        return isset($default) ? $default : null;
                    }
                } else {
                    $filters = explode(',', $filters);
                }
            } elseif (is_int($filters)) {
                $filters = array($filters);
            }

            if (is_array($filters)) {
                foreach ($filters as $filter) {
                    if (function_exists($filter)) {
                        $data = is_array($data) ? array_map_recursive($filter, $data) : $filter($data); // 参数过滤
                    } else {
                        $data = filter_var($data, is_int($filter) ? $filter : filter_id($filter));
                        if (false === $data) {
                            return isset($default) ? $default : null;
                        }
                    }
                }
            }
        }
        if (!empty($type)) {
            switch (strtolower($type)) {
                case 'a':    // 数组
                    $data = (array)$data;
                    break;
                case 'd':    // 数字
                    $data = (int)$data;
                    break;
                case 'f':    // 浮点
                    $data = (float)$data;
                    break;
                case 'b':    // 布尔
                    $data = (boolean)$data;
                    break;
                case 's':   // 字符串
                default:
                    $data = (string)$data;
            }
        }
    } else { // 变量默认值
        $data = isset($default) ? $default : null;
    }
    is_array($data) && array_walk_recursive($data, 'think_filter');
    return $data;
}

function think_filter(&$value)
{
    // TODO 其他安全过滤

    // 过滤查询特殊字符
    if (preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) {
        $value .= ' ';
    }
}

/**
 * 判断是否SSL协议
 * @return boolean
 */
function is_ssl()
{
    if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
        return true;
    } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
        return true;
    }
    return false;
}

/**
 * URL重定向
 * @param string $url 重定向的URL地址
 * @param integer $time 重定向的等待时间（秒）
 * @param string $msg 重定向前的提示信息
 * @return void
 */
if (!function_exists('get_client_ip')) {
    function redirect($url, $time = 0, $msg = '')
    {
        //多行URL地址支持
        $url = str_replace(array("\n", "\r"), '', $url);
        if (empty($msg))
            $msg = "系统将在{$time}秒之后自动跳转到{$url}！";
        if (!headers_sent()) {
            // redirect
            if (0 === $time) {
                header('Location: ' . $url);
            } else {
                header("refresh:{$time};url={$url}");
                echo($msg);
            }
            exit();
        } else {
            $str = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
            if ($time != 0)
                $str .= $msg;
            exit($str);
        }
    }
}


/**
 * 获取客户端IP地址
 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
 * @param boolean $adv 是否进行高级模式获取（有可能被伪装）
 * @return mixed
 */
if (!function_exists('get_client_ip')) {
    function get_client_ip($type = 0, $adv = false)
    {
        $type = $type ? 1 : 0;
        static $ip = NULL;
        if ($ip !== NULL) return $ip[$type];
        if ($adv) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos = array_search('unknown', $arr);
                if (false !== $pos) unset($arr[$pos]);
                $ip = trim($arr[0]);
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip = $_SERVER['HTTP_CLIENT_IP'];
            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u", ip2long($ip));
        $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }
}

/**
 * @todo: 判断是否为post
 */
if (!function_exists('is_post')) {
    function is_post()
    {
        return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) == 'POST';
    }
}

/**
 * @todo: 判断是否为get
 */
if (!function_exists('is_get')) {
    function is_get()
    {
        return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) == 'GET';
    }
}

/**
 * @todo: 判断是否为ajax
 */
if (!function_exists('is_ajax')) {
    function is_ajax()
    {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtoupper($_SERVER['HTTP_X_REQUESTED_WITH']) == 'XMLHTTPREQUEST';
    }
}

/**
 * @todo: 判断是否为命令行模式
 */
if (!function_exists('is_cli')) {
    function is_cli()
    {
        return (PHP_SAPI === 'cli' OR defined('STDIN'));
    }
}

/**
 * 获取x-admin模板的分页
 * @param $total 总数
 * @param $page 当前页
 * @param int $pagesize 每页条数
 */
function getPageHTML($total, $pageIndex, $pageSize = 15, $url = '', $context = array('before' => 5, 'after' => 4, 'ajaxcallback' => '', 'callbackfuncname' => ''))
{
    global $_W;
    $pdata = array(
        'tcount' => 0,
        'tpage' => 0,
        'cindex' => 0,
        'findex' => 0,
        'pindex' => 0,
        'nindex' => 0,
        'lindex' => 0,
        'options' => ''
    );
    if (empty($context['before'])) {
        $context['before'] = 5;
    }
    if (empty($context['after'])) {
        $context['after'] = 4;
    }

    if ($context['ajaxcallback']) {
        $context['isajax'] = true;
    }

    if ($context['callbackfuncname']) {
        $callbackfunc = $context['callbackfuncname'];
    }

    $pdata['tcount'] = $total;
    $pdata['tpage'] = (empty($pageSize) || $pageSize < 0) ? 1 : ceil($total / $pageSize);
    if ($pdata['tpage'] <= 1) {
        return '';
    }
    $cindex = $pageIndex;
    $cindex = min($cindex, $pdata['tpage']);
    $cindex = max($cindex, 1);
    $pdata['cindex'] = $cindex;
    $pdata['findex'] = 1;
    $pdata['pindex'] = $cindex > 1 ? $cindex - 1 : 1;
    $pdata['nindex'] = $cindex < $pdata['tpage'] ? $cindex + 1 : $pdata['tpage'];
    $pdata['lindex'] = $pdata['tpage'];

    if ($context['isajax']) {
        if (empty($url)) {
            $url = $_W['script_name'] . '?' . http_build_query($_GET);
        }
        $pdata['faa'] = 'href="javascript:;" page="' . $pdata['findex'] . '" ' . ($callbackfunc ? 'ng-click="' . $callbackfunc . '(\'' . $url . '\', \'' . $pdata['findex'] . '\', this);"' : '');
        $pdata['paa'] = 'href="javascript:;" page="' . $pdata['pindex'] . '" ' . ($callbackfunc ? 'ng-click="' . $callbackfunc . '(\'' . $url . '\', \'' . $pdata['pindex'] . '\', this);"' : '');
        $pdata['naa'] = 'href="javascript:;" page="' . $pdata['nindex'] . '" ' . ($callbackfunc ? 'ng-click="' . $callbackfunc . '(\'' . $url . '\', \'' . $pdata['nindex'] . '\', this);"' : '');
        $pdata['laa'] = 'href="javascript:;" page="' . $pdata['lindex'] . '" ' . ($callbackfunc ? 'ng-click="' . $callbackfunc . '(\'' . $url . '\', \'' . $pdata['lindex'] . '\', this);"' : '');
    } else {
        if ($url) {
            $pdata['faa'] = 'href="?' . str_replace('*', $pdata['findex'], $url) . '"';
            $pdata['paa'] = 'href="?' . str_replace('*', $pdata['pindex'], $url) . '"';
            $pdata['naa'] = 'href="?' . str_replace('*', $pdata['nindex'], $url) . '"';
            $pdata['laa'] = 'href="?' . str_replace('*', $pdata['lindex'], $url) . '"';
        } else {
            $_GET['page'] = $pdata['findex'];
            $pdata['faa'] = 'href="' . $_W['script_name'] . '?' . http_build_query($_GET) . '"';
            $_GET['page'] = $pdata['pindex'];
            $pdata['paa'] = 'href="' . $_W['script_name'] . '?' . http_build_query($_GET) . '"';
            $_GET['page'] = $pdata['nindex'];
            $pdata['naa'] = 'href="' . $_W['script_name'] . '?' . http_build_query($_GET) . '"';
            $_GET['page'] = $pdata['lindex'];
            $pdata['laa'] = 'href="' . $_W['script_name'] . '?' . http_build_query($_GET) . '"';
        }
    }

    $html = '<div>';
    $html .= "<a {$pdata['faa']} class=\"pager-nav\">首页</a>";
    empty($callbackfunc) && $pageIndex > 1 && $html .= "<a {$pdata['paa']} class=\"prev\">&laquo;上一页</a>";

    if (!$context['before'] && $context['before'] != 0) {
        $context['before'] = 5;
    }
    if (!$context['after'] && $context['after'] != 0) {
        $context['after'] = 4;
    }

    if ($context['after'] != 0 && $context['before'] != 0) {
        $range = array();
        $range['start'] = max(1, $pdata['cindex'] - $context['before']);
        $range['end'] = min($pdata['tpage'], $pdata['cindex'] + $context['after']);
        if ($range['end'] - $range['start'] < $context['before'] + $context['after']) {
            $range['end'] = min($pdata['tpage'], $range['start'] + $context['before'] + $context['after']);
            $range['start'] = max(1, $range['end'] - $context['before'] - $context['after']);
        }
        for ($i = $range['start']; $i <= $range['end']; $i++) {
            if ($context['isajax']) {
                $aa = 'href="javascript:;" page="' . $i . '" ' . ($callbackfunc ? 'ng-click="' . $callbackfunc . '(\'' . $url . '\', \'' . $i . '\', this);"' : '');
            } else {
                if ($url) {
                    $aa = 'href="?' . str_replace('*', $i, $url) . '"';
                } else {
                    $_GET['page'] = $i;
                    $aa = 'href="?' . http_build_query($_GET) . '"';
                }
            }
            if (!empty($context['isajax'])) {
                $html .= ($i == $pdata['cindex'] ? '<span class="current">' : '') . "<a class='num' {$aa}>" . $i . '</a>';
            } else {
                $html .= ($i == $pdata['cindex'] ? '<span class="current">' . $i . '</span>' : "<a class='num' {$aa}>" . $i . '</a>');
            }
        }
    }

    if ($pdata['cindex'] < $pdata['tpage']) {
        empty($callbackfunc) && $html .= "<a {$pdata['naa']} class=\"next\">下一页&raquo;</a>";
        $html .= "<a {$pdata['laa']} class=\"pager-nav\">尾页</a>";
    }
    $html .= '</div>';
    return $html;
}

function create_guid($namespace = '')
{
    static $guid = '';
    $uid = uniqid("", true);
    $data = $namespace;
    $data .= $_SERVER['REQUEST_TIME'];
    $data .= $_SERVER['HTTP_USER_AGENT'];
    $data .= $_SERVER['LOCAL_ADDR'];
    $data .= $_SERVER['LOCAL_PORT'];
    $data .= $_SERVER['REMOTE_ADDR'];
    $data .= $_SERVER['REMOTE_PORT'];
    $hash = strtoupper(hash('ripemd128', $uid . $guid . md5($data)));
    $guid = substr($hash, 0, 8) .
        substr($hash, 8, 4) .
        substr($hash, 12, 4) .
        substr($hash, 16, 4) .
        substr($hash, 20, 12);
    return $guid;
}

function ajaxSuccess($msg = '', $data = '')
{
    $code = 1;
    $result = [
        'code' => $code,
        'msg' => $msg,
        'data' => $data,
    ];
    header('Access-Control-Allow-Origin:*');
    header('Access-Control-Allow-Headers:X-Requested-With,Content-Type,XX-Device-Type,XX-Token');
    header('Access-Control-Allow-Methods:GET,POST,PATCH,PUT,DELETE,OPTIONS');
    echo json_encode($result, JSON_UNESCAPED_UNICODE);
    exit;
}


function ajaxError($msg = '', $data = '')
{
    $code = 0;
    $result = [
        'code' => $code,
        'msg' => $msg,
        'data' => $data,
    ];
    header('Access-Control-Allow-Origin:*');
    header('Access-Control-Allow-Headers:X-Requested-With,Content-Type,XX-Device-Type,XX-Token');
    header('Access-Control-Allow-Methods:GET,POST,PATCH,PUT,DELETE,OPTIONS');
    echo json_encode($result, JSON_UNESCAPED_UNICODE);
    exit;
}

function ajaxReturn($data = array())
{
    header('Access-Control-Allow-Origin:*');
    header('Access-Control-Allow-Headers:X-Requested-With,Content-Type,XX-Device-Type,XX-Token');
    header('Access-Control-Allow-Methods:GET,POST,PATCH,PUT,DELETE,OPTIONS');
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

/* 截取字符串，多余的以省略号代替 */
function cut_str($string, $sublen, $start = 0, $code = 'UTF-8')
{
    if ($code == 'UTF-8') {
        $pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
        preg_match_all($pa, $string, $t_string);
        if (count($t_string[0]) - $start > $sublen) return join('', array_slice($t_string[0], $start, $sublen)) . "...";
        return join('', array_slice($t_string[0], $start, $sublen));
    } else {
        $start = $start * 2;
        $sublen = $sublen * 2;
        $strlen = strlen($string);
        $tmpstr = '';
        for ($i = 0; $i < $strlen; $i++) {
            if ($i >= $start && $i < ($start + $sublen)) {
                if (ord(mb_substr($string, $i, 1)) > 129) {
                    $tmpstr .= mb_substr($string, $i, 2);
                } else {
                    $tmpstr .= mb_substr($string, $i, 1);
                }
            }
            if (ord(mb_substr($string, $i, 1)) > 129) $i++;
        }
        if (strlen($tmpstr) < $strlen) $tmpstr .= "";
        return $tmpstr;
    }
}

function mask_mobile($num, $star_num = 3)
{
    if ($num && strlen($num) == 11) {
        return substr_replace($num, '****', $star_num, 4);
    } else if ($num && strlen($num) != 11) {
        return $num;
    } else {
        return '';
    }
}

/* 检查手机号是否合法 */
function checkMobile($phone)
{
    $preg_phone = '/^1[34578]\d{9}$/';
    if (preg_match($preg_phone, $phone)) {
        return true;
    } else {
        return false;
    }
}

/* 检查固定电话是否合法 */
function checkGuding($call)
{
    $preg_call = '/^(0\d{2,3})?(\d{7,8})$/ims';
    if (preg_match($preg_call, $call)) {
        return true;
    } else {
        return false;
    }
}

/* 检查只包含中英文用户名 */
function checkUsername($name)
{
    $preg_name = '/^[\x{4e00}-\x{9fa5}]{2,10}$|^[a-zA-Z\s]*[a-zA-Z\s]{2,20}$/isu';
    if (preg_match($preg_name, $name)) {
        return true;
    } else {
        return false;
    }
}

/* 检查身份证号是否合法 */
function checkIDcard($IDCard)
{
    $preg_card = '/^\d{15}$)|(^\d{17}([0-9]|X)$/isu';
    if (preg_match($preg_card, $IDCard)) {
        return true;
    } else {
        return false;
    }
}

/* 检查银行卡号是否合法*/
function checkBankCard($bankcard)
{
    $preg_bankcard = '/^(\d{15}|\d{16}|\d{19})$/isu';
    if (preg_match($preg_bankcard, $bankcard)) {
        return true;
    } else {
        return false;
    }
}

/* 验证QQ号是否合法 */
function checkQQ($QQ)
{
    $preg_QQ = '/^\d{5,12}$/isu';
    if (preg_match($preg_QQ, $QQ)) {
        return true;
    } else {
        return false;
    }
}

/* 验证微信号是否合法 */
function checkWechatId($wechat)
{
    $preg_wechat = '/^[_a-zA-Z0-9]{5,19}+$/isu';
    if (preg_match($preg_wechat, $wechat)) {
        return true;
    } else {
        return false;
    }
}

/**
 * 数组 转 对象
 *
 * @param array $arr 数组
 * @return object
 */
function array_to_object($arr)
{
    if (gettype($arr) != 'array') {
        return;
    }
    foreach ($arr as $k => $v) {
        if (gettype($v) == 'array' || getType($v) == 'object') {
            $arr[$k] = (object)array_to_object($v);
        }
    }

    return (object)$arr;
}

/**
 * 对象 转 数组
 *
 * @param object $obj 对象
 * @return array
 */
function object_to_array($obj)
{
    $obj = (array)$obj;
    foreach ($obj as $k => $v) {
        if (gettype($v) == 'resource') {
            return;
        }
        if (gettype($v) == 'object' || gettype($v) == 'array') {
            $obj[$k] = (array)object_to_array($v);
        }
    }

    return $obj;
}

function cmf_set_option($key, $data, $replace = false)
{
    if (!is_array($data) || empty($data) || !is_string($key) || empty($key)) {
        return false;
    }

    $key = strtolower($key);
    $option = [];
    $findOption = pdo_get('yq_haircircle_option', array('option_name' => $key));
    if ($findOption) {
        if (!$replace) {
            $oldOptionValue = json_decode($findOption['option_value'], true);
            if (!empty($oldOptionValue)) {
                $data = array_merge($oldOptionValue, $data);
            }
        }

        $option['option_value'] = json_encode($data);
        pdo_update('yq_haircircle_option', $option, array('option_name' => $key));
    } else {
        $option['option_name'] = $key;
        $option['option_value'] = json_encode($data);
        pdo_insert('yq_haircircle_option', $option);
    }
//    cache_delete('cmf_options_' . $key);
    return true;
}

/**
 * 获取系统配置，通用
 * @param string $key 配置键值,都小写
 * @return array
 */
function cmf_get_option($key, $update = true)
{
    if (!is_string($key) || empty($key)) {
        return [];
    }

    static $cmfGetOption;

    if (empty($cmfGetOption)) {
        $cmfGetOption = [];
    } else {
        if (!empty($cmfGetOption[$key])) {
            return $cmfGetOption[$key];
        }
    }

//    $optionValue = null;
//    if (!$update) {
//        $optionValue = cache_load('cmf_options_' . $key);
//    }

    if (empty($optionValue)) {
        $optionValue = pdo_getcolumn('yq_haircircle_option', array('option_name' => $key), 'option_value');
        if (!empty($optionValue)) {
            $optionValue = json_decode($optionValue, true);
//            cache_write('cmf_options_' . $key, $optionValue);
        }
    }
    $cmfGetOption[$key] = $optionValue;

    return $optionValue;
}

function cmf_config($str, $value = null)
{
    if (empty($str) || !is_string($str)) return false;
    if (!is_file($file = MODULE_ROOT . DS . 'config.php')) {
        return false;
    }
    $config = require $file;
    //读配置
    if (is_null($value)) {
        if (false !== stripos($str, '.')) {
            $arr = explode('.', $str);
            $count = count($arr);
            if ($count > 3) return false;
            if ($count == 1) return isset($config[$str]) ? $config[$str] : false;
            if ($count == 2) return isset($config[$arr[0]][$arr[1]]) ? $config[$arr[0]][$arr[1]] : false;
        } else {
            isset($config[$str]) ? $config[$str] : false;
        }
    } else {
        //写配置
        if (false !== stripos($str, '.')) {
            $arr = explode('.', $str);
            $count = count($arr);
            if ($count == 1) {
                $config[$str] = $value;
            } else if ($count == 2) {
                $config[$arr[0]][$arr[1]] = $value;
            } else {
                return false;
            }
        } else {
            $config[$str] = $value;
        }
        $str = '<?php return array(';
        foreach ($config as $key => $value) {
            if (is_array($value)) {
                $str .= '\'' . $key . '\'' . '=>array(';
                foreach ($value as $k => $v) {
                    $str .= '\'' . $k . '\'' . '=>' . '\'' . $v . '\'' . ',';
                }
                $str .= '),';
            } else {
                $str .= '\'' . $key . '\'' . '=>' . '\'' . $value . '\'' . ',';
            }
        };
        $str .= '); ';
        return file_put_contents($file, $str);//写入文件
    }
}

/**
 * CMF密码加密方法
 * @param string $pw 要加密的原始密码
 * @param string $authCode 加密字符串
 * @return string
 */
function cmf_password($pw, $authCode = '')
{
    if (empty($authCode)) {
        $authCode = cmf_config('database.authcode');
    }
    $result = "###" . md5(md5($authCode . $pw));
    return $result;
}

/**
 * CMF密码比较方法,所有涉及密码比较的地方都用这个方法
 * @param string $password 要比较的密码
 * @param string $passwordInDb 数据库保存的已经加密过的密码
 * @return boolean 密码相同，返回true
 */
function cmf_compare_password($password, $passwordInDb)
{
    if (strpos($passwordInDb, "###") === 0) {
        return cmf_password($password) == $passwordInDb;
    } else {
        return cmf_password_old($password) == $passwordInDb;
    }
}

/**
 * 文件日志
 * @param $content 要写入的内容
 * @param string $file 日志文件,在web 入口目录
 */
function cmf_log($content, $file = "log.txt")
{
    file_put_contents($file, $content, FILE_APPEND);
}

/**
 * 发送短信
 */
function cmf_send_sms($mobile, $message)
{
    $sms = new XlnSmsAPI();
    if (!$sms->send($mobile, $message)) {
        $mailError = $sms->ErrorInfo;
        return ["error" => 1, "message" => $mailError];
    } else {
        return ["error" => 0, "message" => "success"];
    }
}

/**
 * 解密用cmf_str_encode加密的字符串
 * @param $string 要解密的字符串
 * @param string $key 加密时salt
 * @param int $expiry 多少秒后过期
 * @param string $operation 操作,默认为DECODE
 * @return bool|string
 */
function cmf_str_decode($string, $key = '', $expiry = 0, $operation = 'DECODE')
{
    $ckey_length = 4;

    $key = md5($key ? $key : config("authcode"));
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';

    $cryptkey = $keya . md5($keya . $keyc);
    $key_length = strlen($cryptkey);

    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
    $string_length = strlen($string);

    $result = '';
    $box = range(0, 255);

    $rndkey = [];
    for ($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }

    for ($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for ($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }

    if ($operation == 'DECODE') {
        if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        return $keyc . str_replace('=', '', base64_encode($result));
    }

}

/**
 * 加密字符串
 * @param $string 要加密的字符串
 * @param string $key salt
 * @param int $expiry 多少秒后过期
 * @return bool|string
 */
function cmf_str_encode($string, $key = '', $expiry = 0)
{
    return cmf_str_decode($string, $key, $expiry, "ENCODE");
}

/**
 * 检测是否使用手机访问
 * @access public
 * @return bool
 */
function isMobile()
{
    if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) {
        return true;
    } elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) {
        return true;
    } elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
        return true;
    } elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) {
        return true;
    } else {
        return false;
    }
}

function cmf_is_mobile()
{
    static $cmf_is_mobile;

    if (isset($cmf_is_mobile))
        return $cmf_is_mobile;

    $cmf_is_mobile = isMobile();

    return $cmf_is_mobile;
}

/**
 * 判断是否为微信访问
 * @return boolean
 */
function cmf_is_wechat()
{
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false) {
        return true;
    }
    return false;
}

/**
 * 判断是否为Android访问
 * @return boolean
 */
function cmf_is_android()
{
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false) {
        return true;
    }
    return false;
}

/**
 * 判断是否为ios访问
 * @return boolean
 */
function cmf_is_ios()
{
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')) {
        {
            return true;
        }
        return false;
    }
}

/**
 * 判断是否为iPhone访问
 * @return boolean
 */
function cmf_is_iphone()
{
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone')) {
        {
            return true;
        }
        return false;
    }
}

/**
 * 判断是否为iPad访问
 * @return boolean
 */
function cmf_is_ipad()
{
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')) {
        {
            return true;
        }
        return false;
    }
}

/**
 * 替代scan_dir的方法
 * @param string $pattern 检索模式 搜索模式 *.txt,*.doc; (同glog方法)
 * @param int $flags
 * @param $pattern
 * @return array
 */
function cmf_scan_dir($pattern, $flags = null)
{
    $files = glob($pattern, $flags);
    if (empty($files)) {
        $files = [];
    } else {
        $files = array_map('basename', $files);
    }

    return $files;
}

/**
 * 获取某个目录下所有子目录
 * @param $dir
 * @return array
 */
function cmf_sub_dirs($dir)
{
    $dir = ltrim($dir, "/");
    $dirs = [];
    $subDirs = cmf_scan_dir("$dir/*", GLOB_ONLYDIR);
    if (!empty($subDirs)) {
        foreach ($subDirs as $subDir) {
            $subDir = "$dir/$subDir";
            array_push($dirs, $subDir);
            $subDirSubDirs = cmf_sub_dirs($subDir);
            if (!empty($subDirSubDirs)) {
                $dirs = array_merge($dirs, $subDirSubDirs);
            }
        }
    }

    return $dirs;
}

/**
 * 获取惟一订单号
 * @return string
 */
function cmf_get_order_sn()
{
    return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}

/**
 * 获取文件扩展名
 * @param string $filename 文件名
 * @return string 文件扩展名
 */
function cmf_get_file_extension($filename)
{
    $pathinfo = pathinfo($filename);
    return strtolower($pathinfo['extension']);
}

/**
 * 检查手机或邮箱是否还可以发送验证码,并返回生成的验证码
 * @param string $account 手机或邮箱
 * @param integer $length 验证码位数,支持4,6,8
 * @return string 数字验证码
 */
function cmf_get_verification_code($account, $length = 6)
{
    if (empty($account)) return false;
    $currentTime = time();
    $maxCount = 10;

    $findVerificationCode = pdo_get('yq_haircircle_verification_code', array('account' => $account));

    if (!empty($findVerificationCode)) {
        $sendTime = $findVerificationCode['send_time'];
        $todayStartTime = strtotime(date('Y-m-d', $currentTime));
        if ($sendTime > $todayStartTime && $findVerificationCode['count'] >= $maxCount) {
            return false;
        }
    }

    switch ($length) {
        case 4:
            $result = rand(1000, 9999);
            break;
        case 6:
            $result = rand(100000, 999999);
            break;
        case 8:
            $result = rand(10000000, 99999999);
            break;
        default:
            $result = rand(100000, 999999);
    }

    return $result;
}

/**
 * 更新手机或邮箱验证码发送日志
 * @param string $account 手机或邮箱
 * @param string $code 验证码
 * @param int $expireTime 过期时间
 * @return boolean
 */
function cmf_verification_code_log($account, $code, $expireTime = 0)
{
    $currentTime = time();
    $expireTime = $expireTime > $currentTime ? $expireTime : $currentTime + 30 * 60;
    $findVerificationCode = pdo_get('yq_haircircle_verification_code', array('account' => $account));
    if ($findVerificationCode) {
        $todayStartTime = strtotime(date("Y-m-d"));//当天0点
        if ($findVerificationCode['send_time'] <= $todayStartTime) {
            $count = 1;
        } else {
            $count = $findVerificationCode['count'] + 1;
        }
        $result = pdo_update('yq_haircircle_verification_code', [
            'send_time' => $currentTime,
            'expire_time' => $expireTime,
            'code' => $code,
            'count' => $count
        ], array('account' => $account));
    } else {
        $result = pdo_insertid('yq_haircircle_verification_code', [
            'account' => $account,
            'send_time' => $currentTime,
            'code' => $code,
            'count' => 1,
            'expire_time' => $expireTime
        ]);
    }

    return $result;
}

/**
 * 手机或邮箱验证码检查，验证完后销毁验证码增加安全性,返回true验证码正确，false验证码错误
 * @param string $account 手机或邮箱
 * @param string $code 验证码
 * @param boolean $clear 是否验证后销毁验证码
 * @return string  错误消息,空字符串代码验证码正确
 */
function cmf_check_verification_code($account, $code, $clear = false)
{
    $findVerificationCode = pdo_get('yq_haircircle_verification_code', array('account' => $account));

    if ($findVerificationCode) {
        if ($findVerificationCode['expire_time'] > time()) {

            if ($code == $findVerificationCode['code']) {
                if ($clear) {
                    pdo_update('yq_haircircle_verification_code', ['code' => ''], array('account' => $account));
                }
            } else {
                return "验证码不正确!";
            }
        } else {
            return "验证码已经过期,请先获取验证码!";
        }

    } else {
        return "请先获取验证码!";
    }

    return "";
}

/**
 * 清除某个手机或邮箱的数字验证码,一般在验证码验证正确完成后
 * @param string $account 手机或邮箱
 * @return boolean true：手机验证码正确，false：手机验证码错误
 */
function cmf_clear_verification_code($account)
{
    pdo_update('yq_haircircle_verification_code', ['code' => ''], array('account' => $account));
}

/**
 * curl get 请求
 * @param $url
 * @return mixed
 */
function cmf_curl_get($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_FAILONERROR, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_AUTOREFERER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    $SSL = substr($url, 0, 8) == "https://" ? true : false;
    if ($SSL) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名
    }
    $content = curl_exec($ch);
    curl_close($ch);
    return $content;
}

/**
 * XML编码
 * @param mixed $data 数据
 * @param string $root 根节点名
 * @param string $item 数字索引的子节点名
 * @param string $attr 根节点属性
 * @param string $id 数字索引子节点key转换的属性名
 * @param string $encoding 数据编码
 * @return string
 */
function cmf_xml_encode($data, $root = 'think', $item = 'item', $attr = '', $id = 'id', $encoding = 'utf-8')
{
    if (is_array($attr)) {
        $_attr = [];
        foreach ($attr as $key => $value) {
            $_attr[] = "{$key}=\"{$value}\"";
        }
        $attr = implode(' ', $_attr);
    }
    $attr = trim($attr);
    $attr = empty($attr) ? '' : " {$attr}";
    $xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
    $xml .= "<{$root}{$attr}>";
    $xml .= cmf_data_to_xml($data, $item, $id);
    $xml .= "</{$root}>";
    return $xml;
}

/**
 * 数据XML编码
 * @param mixed $data 数据
 * @param string $item 数字索引时的节点名称
 * @param string $id 数字索引key转换为的属性名
 * @return string
 */
function cmf_data_to_xml($data, $item = 'item', $id = 'id')
{
    $xml = $attr = '';
    foreach ($data as $key => $val) {
        if (is_numeric($key)) {
            $id && $attr = " {$id}=\"{$key}\"";
            $key = $item;
        }
        $xml .= "<{$key}{$attr}>";
        $xml .= (is_array($val) || is_object($val)) ? cmf_data_to_xml($val, $item, $id) : $val;
        $xml .= "</{$key}>";
    }
    return $xml;
}

/**
 * 检查手机格式，中国手机不带国家代码，国际手机号格式为：国家代码-手机号
 * @param $mobile
 * @return bool
 */
function cmf_check_mobile($mobile)
{
    if (preg_match('/(^(13\d|14\d|15\d|16\d|17\d|18\d|19\d)\d{8})$/', $mobile)) {
        return true;
    } else {
        if (preg_match('/^\d{1,4}-\d{5,11}$/', $mobile)) {
            if (preg_match('/^\d{1,4}-0+/', $mobile)) {
                //不能以0开头
                return false;
            }

            return true;
        }

        return false;
    }
}

function dump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE)
{
    $label = (null === $label) ? '' : rtrim($label) . ':';

    ob_start();
    var_dump($var);
    $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', ob_get_clean());

    if (IS_CLI) {
        $output = PHP_EOL . $label . $output . PHP_EOL;
    } else {
        if (!extension_loaded('xdebug')) {
            $output = htmlspecialchars($output, $flags);
        }

        $output = '<pre>' . $label . $output . '</pre>';
    }

    if ($echo) {
        echo($output);
        return;
    }

    return $output;
}